#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/msg.h>
#include <sys/ipc.h>

#include <syslog.h>

#include "../include/TCPserver.h"
#include "../include/queries.h"
#include "../databaseADT/databaseADT.h"
#include "../../common/include/commonTCP.h"
#include "../../common/include/general.h"
#include "../../common/include/common.h"
#include "../../common/include/split.h"
#include "../include/server.h"

#define SOCK_SIZE   sizeof(struct sockaddr_in)
#define QUEUE_ID    100

/* Externs de server.c */
extern char splitVal;
extern splitNode splits[MAX_SPLITS];
extern int doLC;

void catcher (int sig, int newsockfd);
int doLQ = 1;

struct mymsg {
    long      mtype;    /* message type */
    char mtext[FILE_LEN]; /* message text of length MSGSZ */
};

int mqid;
int fdpub;

int
mainTCP (void)
{
    int i, splitRet;

    mqid = msgget((key_t)QUEUE_ID, 0666 | IPC_CREAT);

    if ((i = getOnlineFreeID(NULL)) == -1)
    {
        fatal(  "ERROR: Can't get a free slot in split vec.\n"
                "SOLUTION: Check MAX_SPLITS.\n");
        return -1;
    }

    /* Handlers de SIGS */
    (void)signal(SIGINT, sighandLCTCP);

    /* Actualizo online */
    modifyOnline(i, i, NULL, 1);

    /*Se splitea dependiendo de los parámetros.*/
    if (splitVal == 't')
        splitRet = split(listenQueueTCP, NULL, (void *)&splits[i].thread, splitVal,
                        endCiclesTCP);
    else
        splitRet = split(listenQueueTCP, NULL, (void *)&splits[i].cID, splitVal,
                        endCiclesTCP);

    if ( splitRet != 1)
        return fatal ("Split failed with listenQueueTCP\n");


    if ((i = getOnlineFreeID(NULL)) == -1)
    {
        fatal(  "ERROR: Can't get a free slot in split vec.\n"
                "SOLUTION: Check MAX_SPLITS.\n");
        return -1;
    }

    /* Actualizo online */
    modifyOnline(i, i, NULL, 1);

    /*Se splitea dependiendo de los parámetros.*/
    if (splitVal == 't')
        splitRet = split(listenPubTCP, NULL, (void *)&splits[i].thread, splitVal,
                        endCiclesTCP);
    else
        splitRet = split(listenPubTCP, NULL, (void *)&splits[i].cID, splitVal,
                        endCiclesTCP);

    if ( splitRet != 1)
        return fatal ("Split failed with listenPubTCP\n");

    readCommandsTCP();

    return 0;
}

void * listenPubTCP (void * paramsTCP)
{
    int newsockfd;
    fd_set master_set, working_set;
    char ch;
    struct sockaddr_in server = { AF_INET, 1234, {INADDR_ANY} };
    static struct sigaction act;
    int i, splitRet;
    struct sockyID * params;
    struct timeval tw, tm;

    act.sa_handler = (void *)catcher;
    sigfillset(&(act.sa_mask));

    sigaction(SIGPIPE, &act, NULL);

    /* set up the transport end point */
    if((fdpub = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        fatal(  "ERROR: Socket creation failed.\n"
                "SOLUTION: Check TCPserver.c.\n");
        return (void *)NULL;
    }

    /* bind an address to the end point */
    if (bind(fdpub, (struct sockaddr *)&server, SOCK_SIZE) == -1)
    {
        fatal(  "ERROR: Bind call failed.\n"
                "SOLUTION: Check TCPserver.c.\n");
        close(fdpub);
        exitSplit(splitVal);
    }

    /* start listening for incoming connections */
    if (listen(fdpub, 5) == -1)
    {
        fatal(  "ERROR: Listen call failed.\n"
                "SOLUTION: Check TCPserver.c.\n");
        close(fdpub);
        exitSplit(splitVal);
    }

    tm.tv_sec  = SEC_TIMEOUT;
    tm.tv_usec = 0;
    FD_ZERO(&master_set);
    FD_SET(fdpub, &master_set);


    while (doLC)
    {
        memcpy(&working_set, &master_set, sizeof(master_set));
        memcpy(&tw, &tm, sizeof(struct timeval));
        if(select(fdpub+1, &working_set, (fd_set *)0, (fd_set *)0, &tw) < 0)
        {
            if (errno == EINTR)
                continue;
            else
                fatal(  "ERROR: Select failed.\n"
                        "SOLUTION: Check TCPserver.c.\n");
        }

        if (FD_ISSET (0, &working_set))
        {
            read(0, &ch, 1);
            printf("%c\n", ch);
        }

        if (FD_ISSET (fdpub, &working_set))
        {

                /* accept a connection */
            if ((newsockfd = accept(fdpub, NULL, NULL)) == -1)
            {
                fatal(  "ERROR: Accept call failed.\n"
                        "SOLUTION: Check TCPserver.c.\n");
                continue;
            }

            if ((params = malloc (sizeof(struct sockyID))) == NULL)
            {
                fatal(  "ERROR: Malloc.\n");
                return (void *)NULL;
            }

            if ((i = getOnlineFreeID(NULL)) == -1)
            {
                fatal(  "ERROR: Can't get a free slot in split vec.\n"
                        "SOLUTION: Check MAX_SPLITS.\n");
                return (void *)NULL;
            }

            /* Actualizo online */
            modifyOnline(i, i, NULL, 1);

            params->cliID = i;
            params->fdsock = newsockfd;

            /*Se splitea dependiendo de los parámetros.*/
            if (splitVal == 't')
                splitRet = split(listenPrivTCP, (void *) params,
                                (void *)&splits[i].thread, splitVal, NULL);
            else
                splitRet = split(listenPrivTCP, (void *) params,
                                (void *)&splits[i].cID, splitVal, NULL);

            if ( splitRet != 1)
            {
                fatal ("Split failed with listenPubTCP\n");
                return (void *)NULL;
            }
        }
    }
    close(fdpub);
    return (void *)NULL;
}

void * listenPrivTCP (void * paramsTCP)
{
    char msgbuf[MSGSIZE+1] = {0};
    fd_set prfds;
    fd_set wprfds;
    int newsockfd = ((struct sockyID*) paramsTCP)->fdsock;
    int  sonid = ((struct sockyID*) paramsTCP)->cliID;
    struct timeval tw, tm;

    tm.tv_sec  = SEC_TIMEOUT;
    tm.tv_usec = 0;


    FD_ZERO(&prfds);
    FD_SET(newsockfd, &prfds);
    for (;;)
    {
        if (listenQueueSonTCP(newsockfd, sonid) < 0)
            return (void *)NULL;

        memcpy(&wprfds, &prfds, sizeof(prfds));
        memcpy(&tw, &tm, sizeof(struct timeval));
        if(select(newsockfd+1, &wprfds, (fd_set *)0, (fd_set *)0, &tw) < 0)
        {
            if (errno == EINTR)
                continue;
            else
            {
                fatal ("select failed\n");
                return (void *)NULL;
            }
        }

        if (FD_ISSET(newsockfd, &wprfds))
        {
            clrtext(msgbuf,MSGSIZE+1);
            if (read (newsockfd, msgbuf, MSGSIZE+1) < 0)
            {
                fatal ("msg read failed\n");
                return (void *)NULL;
            }

            /* Me fijo si es un commit.
             Si es, creo el .new para evitar conflictos*/
            if (canCommittTCP(msgbuf, newsockfd))
            {
                waitPckTCP (newsockfd, msgbuf, sonid);
            }
        }
    }
    return (void *)NULL;
}

void readCommandsTCP(void)
{
    int i;
    int cant_comms = 7;
    char command[MAX_COMMAND_LEN+1] = {0};
    char * param;
    char * commands[] = {"registrar", "usuarios", "dir", "last10",
                        "Ulast10", "newDir", "salir"};

    void (*pFunct[]) (char *)= {registrar, usuarios, dir, last10, ulast10,
                                newDir, salirTCP};

    fprintf (stdout, "\n<>: ");
    getLine (command, MAX_COMMAND_LEN, stdin);

    for (i=0 ; i < cant_comms+1 ; i++)
    {
        if (i == cant_comms)
        {
           fprintf (stdout, "\nError: Invalid command\n<>: ");
           getLine (command, MAX_COMMAND_LEN, stdin);
           i = -1;
        }
        else if (strcmp (command, commands[i]) == 0)
        {
            if(i == 6)
                salirTCP(NULL);

            pFunct[i] (param);
            fprintf (stdout, "\n<>: ");
            getLine (command, MAX_COMMAND_LEN, stdin);
            i = -1;
        }
    }

    return ;
}

int waitPckTCP (int newsockfd, char * msg, int sonid)
{

    int com;
    int size;
    char params[50] = {0};
    char full[100] = {0};

    sscanf(msg, "%d,%d,%s", &com, &size, full);

    full[size] = 0;

    strcpy(params, full);

    switch(com)
    {
        case COM_NAME:
            return addnameTCP(params, newsockfd, sonid);
            break;

        case COM_LIST:
            listdirsTCP(newsockfd);
            break;

        case COM_ADD:
            (void)adddirTCP(full, newsockfd, sonid);
            break;

        case COM_REMOVE:
           (void)removedirTCP(params, newsockfd);
            break;

        case COM_CLOSE:
            closesessTCP(newsockfd);
            exitSplit(splitVal);
            break;

        case COM_COMMIT:
            rcvCommitTCP(params, newsockfd);
            break;

        default:
            break;
    }


    return 0; // para diferenciar de nombre ke devuelve el id
}

void salirTCP(char * param)
{
    closeALLTCP();
    return;
}

int addnameTCP (char * name, int newsockfd, int id)
{
//    int id;
    char priv[100] = {0};
    sprintf(priv, "%d", newsockfd);

    if (addUser(name, priv) == DB_INTERNAL_ERROR)
    {
        sndTCPAns(newsockfd, COM_ERR);
        return fatal(   "ERROR: Database error In addname.\n"
                        "SOLUTION: Check Database status.\n");
    }

//    id = userID(name);
    modifyOnline(id, id, name, 1);

/*    switch(DBconnect(name))
    {
        case DB_INTERNAL_ERROR:
            sndTCPAns(newsockfd, COM_ERR);
            return fatal(   "ERROR: Database error In addname.\n"
                            "SOLUTION: Check Database status.\n");
            break;

        case DB_ALREADY_EXISTS:
            sndTCPAns(newsockfd, COM_ERR);
            fprintf(stderr, "ERROR: User %s already logged\n", name);
            return fatal(   "SOLUTION: If this persist, ban him. :)\n");
            break;

        case DB_NO_SLOTS:
            sndTCPAns(newsockfd, COM_ERR);
            return fatal(   "ERROR: No more slots available.\n"
                            "SOLUTION: Check MAX_SPLITS.\n");
            return -1;
            break;

        default:
            break;
    }
*/
    sndTCPAns(newsockfd, COM_ACK);

    addLog(priv, "Logged in");

    return id;

}

void adddirTCP (char * dir, int newsockfd, int sonid)
{
    char answ[50] = {0};
    int len, back, resp;
    char path[MAX_DIR_LEN + 7] = {0};
    char logact[100] = {0};
    queueADT dirs;
    int qlen, flag = 1;
    char *aux_dir;
    char priv[100] = {0};

    sprintf(priv, "%d", newsockfd);
    if(isSynched(sonid, dir))
    {
        sndTCPAns(newsockfd, IS_SYNC);
        return ;
    }

    dirs = listDir();
    qlen = queueLength(dirs);

    while (qlen-- && flag)
    {
        aux_dir = (char *)dequeue ( dirs );
        if (strcmp(dir, aux_dir) == 0)
            flag = 0;

        free(aux_dir);
    }

    if (flag)
    {
        sndTCPAns(newsockfd, DIR_ERR);
        return;
    }

    len = strlen(dir);
    sprintf(answ, "%d,%d,%s", COM_SND_FILES, len, dir);

    len = strlen((char *)answ);
    send_data_TCP (newsockfd, answ, len);
    back = rcvTCPAns(newsockfd);

    resp = addFifoDir(priv,dir);

    sprintf (path, "./%s", dir);
    if (walkDirTCP(path, "", newsockfd) <= 0)
    {
        fatal ("Dir send failed\n");
    }

    sndTCPAns(newsockfd, COM_END);

    strcpy (logact, "Sync dir: ");
    strcat(logact, dir);
    addLog(priv, logact);

    return;
}

void removedirTCP (char * dir, int newsockfd)
{
    DB_ERR ans;
    char logact[100] = {0};
    int len = 0;
    char answ[MSGSIZE+1] = {0};

    char priv[MSGSIZE+1] = {0};

    sprintf(priv, "%d", newsockfd);
    if ((ans = removeDirByFifo(priv, dir)) != DB_SUCCESS)
    {
        sndTCPAns(newsockfd, COM_ERR);
        fatal ("DB Failure\n");
    }

    len = strlen(dir);
    sprintf(answ, "%d,%d,%s", COM_RMV_OK, len, dir);

    len = strlen((char *)answ);

    send_data_TCP (newsockfd, answ, len);

    strcpy (logact, "Remove sync: ");
    strcat(logact, dir);
    addLog(priv, logact);

    return;
}

void listdirsTCP (int newsockfd)
{
    char answ[50] = {0};
    int len, nwrite;
    char priv[MSGSIZE+1] = {0};

    sprintf(priv, "%d", newsockfd);
    sprintf(answ, "%d", COM_SND_DIRLIST);

    len = strlen((char *)answ);

    if ((nwrite = write(newsockfd, answ, len)) == -1)
        fatal("message write failed\n");


    if (rcvTCPAns(newsockfd) != COM_ACK)
    {
        fatal ("Error msg received\n");
    }

    if (sndlistTCP (newsockfd) < 0)
    {
        fatal ("List could not be sent correctly\n");
    }

    addLog(priv, "List dirs");

    return;
}

void closesessTCP (int newsockfd)
{
    DB_ERR ans;
    char priv[MSGSIZE+1] = {0};

    sprintf(priv, "%d", newsockfd);
    if ((ans = disconnectFifo(priv)) != DB_SUCCESS)
    {
        sndTCPAns(newsockfd, COM_ERR);
        fatal ("DB Failure\n");
    }

    addLog(priv, "Logged Out");

    close(newsockfd);

    return;
}

int getparamsTCP (char * full, char * params)
{
    char c;
    char priv[100] = {0};
    int i = 0;

    c = *full++;
    while (c != ',' && c != 0)
    {
        priv[i++] = c;
        c = *full++;
    }
    if (c == 0)
        return i;

    sprintf(params,"%s", priv);
    return i+1;
}

int sndlistTCP (int newsockfd)
{
    queueADT dirs;
    int name_len, tot_len, cant;

    char answ[MSGSIZE + 1] = {0};
    int back;

    char * name;

    dirs = listDir();
    cant = queueLength(dirs);

    while (cant--)
    {
        name = (char *)dequeue ( dirs );
        name_len = strlen( name);
        sprintf(answ, "%d,%d,%s", SND_DIR_NAME, name_len, name);

        tot_len = strlen (answ);

        do
        {
            if ((send_data_TCP (newsockfd, answ, tot_len)) < 0)
            {
                fatal ("send dir failed\n");
                return -1;
            }


            back = rcvTCPAns(newsockfd);

        }while (back != COM_ACK);
    }


    freeQueue( dirs );
    sndTCPAns(newsockfd, COM_END);

    return 1;
}

void rcvCommitTCP (char * params, int newsockfd)
{
    char answ[50] = {0};
    char buffer[BUF_SIZE] = {0};
    char newpath[100] = {0};
    FILE * pfile;
    int len, nread, size;
    int path_size, comm, type, i = 0;
    char path[100] = {0};
    char msgbuf[100] = {0};
    char logact[100] = {0};
    char dir[FILE_LEN] = {0};
    char priv[MSGSIZE+1] = {0};

    sprintf(priv, "%d", newsockfd);
    char cliName[100] = {0};

    do
    {
        cliName[i++] = *(params++);
    }
    while (*params != ',');
    params++;

    getDirType(params, dir, &type);

    if (type == ADD_MOD)
    {
        len = strlen(dir);
        sprintf(answ, "%d,%d,%s", COM_RCV_COMMIT, len, dir);

        len = strlen((char *)answ);

        send_data_TCP (newsockfd, answ, len);

        comm = readcomTCP (newsockfd);

        if (comm == SND_FILE)
        {

            path_size = readsizeTCP (newsockfd);

            if (read (newsockfd, msgbuf, path_size) < 0)
                fatal ("msg read failed\n");

            msgbuf[path_size] = 0;
            sscanf (msgbuf, "%d,%s", &size, path);

            sprintf(newpath, "%s.new", path);

            if (size == -1)
            {
                if(mkdir(path, 0777) == -1)
                {
                    printf("ERROR: creating dir: %s\n", path);
                    sndTCPAns(newsockfd, COM_ERR);
                    return ;
                }
                if (remove(newpath) != 0)
                {
                    printf("ERROR: removing dir: %s\n", newpath);
                    sndTCPAns(newsockfd, COM_ERR);
                    return ;
                }
                sndTCPAns(newsockfd, COM_ACK);
            }
            else
            {

                if((pfile = fopen(newpath, "w")) == NULL)
                    fatal ("Error creating file\n");

                nread = 0;
                sndTCPAns(newsockfd, COM_ACK);
                while (size > 0)
                {
                    if (size >= BUF_SIZE)
                        nread = BUF_SIZE;
                    else
                        nread = size;

                    if (read (newsockfd, buffer, nread) < 0)
                        {
                            sndTCPAns(newsockfd, COM_ERR);
                            printf ("msg read failed\n");
                        }

                    if ((fwrite(buffer, 1, nread, pfile)) < nread)
                    {
                        sndTCPAns(newsockfd, COM_ERR);
                        printf ("File write failed\n");
                    }

                    sndTCPAns(newsockfd, COM_ACK);

                    size -= nread;

                }

                if ((fclose (pfile)) == EOF)
                    printf ("file close failed\n");

                if (rename(newpath, path) != 0)
                {
                    printf ("Error renaming %s\n", newpath);
                    exitSplit(splitVal);
                }
            }
        }

        if (forwardTCP (cliName, path, type) < 0)
        {
            printf("Error forwarding %s\n", path);
        }

        strcpy(logact, "Commited (add/mod): ");
        strcat (logact, path);

        addLog(priv, logact);
        sndTCPAns(newsockfd, COM_ACK);

    }

    else if(type == DEL_COMMIT)
    {
        if (remove(dir) != 0)
        {
            sndTCPAns(newsockfd, COM_ERR);
        }

        else
        {
            if (forwardTCP (cliName, dir, type) < 0)
            {
                printf("Error forwarding %s\n", path);
            }
            strcpy(logact, "Commited (del): ");
            strcat (logact, dir);

            addLog(priv, logact);

            sndTCPAns(newsockfd, COMMIT_OK);
        }

    }
    else if(type == DEL_DIR_COMMIT)
    {
        if (rmdir(dir) != 0)
        {
            sndTCPAns(newsockfd, COM_ERR);
        }

        else
        {
            if (forwardTCP (cliName, dir, type) < 0)
            {
                printf("Error forwarding %s\n", path);
            }
            strcpy(logact, "Commited (del): ");
            strcat (logact, dir);

            addLog(priv, logact);

            sndTCPAns(newsockfd, COMMIT_OK);
        }

    }

    return;
}

int srv_commitTCP (int newsockfd, char * path, int type)
{
    int back, len;
    char dir[MAX_DIR_LEN] = {0};
    char answ[50] = {0};
    char aux_msg[FILE_LEN] = {0};

    char priv[MSGSIZE+1] = {0};

    sprintf(priv, "%d", newsockfd);

    getDir (dir, path);
    len = strlen(dir);

    sprintf(aux_msg, "%s,%d", path, type);
    len = strlen((char *)aux_msg);
    len += 1;
    sprintf(answ, "%d,%d,%s", COM_SND_COMMIT, len, aux_msg);

    len = strlen((char *)answ);

    send_data_TCP (newsockfd, answ, len);

    back = rcvTCPAns(newsockfd);

    if (type == ADD_MOD)
    {
        if (snd_file_TCP (newsockfd, path, 0) < 0)
        {
            printf ("%s not sent to %d\n", path, newsockfd);
        }
    }

    return 1;
}

int canCommittTCP(char * msg, int fd)
{
    FILE * pfile;
    int com, i = 0;
    int size;
    char full[100] = {0};
    int type;
    char dir[FILE_LEN] = {0};
    char newpath[100] = {0};
    int len;
    char answ[FILE_LEN] = {0};
    char sess_name[100] = {0};



    sscanf(msg, "%d,%d,%s", &com, &size,full);

    if (com != COM_COMMIT)
        return 1;

    full[size] = 0;

    i= getparamsTCP(full, sess_name);
    getDirType(&(full[i]), dir, &type);

    sprintf(newpath, "%s.new", dir);

    if((pfile = fopen(newpath, "r")) == NULL)
    {
        if (type == DEL_COMMIT)
            return 1;
        if (type == DEL_DIR_COMMIT)
            return 1;
        if((pfile = fopen(newpath, "w")) == NULL)
        {
            fatal ("file open failed\n");
            return -1;
        }

        if (fclose(pfile) == EOF)
        {
            fatal ("file close failed\n");
            return -1;
        }
        return 1;
    }


    len = strlen(dir);
    sprintf(answ, "%d,%d,%s", WILL_UPDATE, len, dir);

    len = strlen((char *)answ);
    send_data_TCP (fd, answ, len);


    return 0;
}

void catcher (int sig, int newsockfd)
{
    close(newsockfd);
    exitSplit(splitVal);
}

void * listenQueueTCP(void * paramsTCP)
{
    struct mymsg msg;
    int com, rtrn, commtype;
    char path[FILE_LEN] = {0};
    char name[100] = {0};
    struct mymsg sbuf;
    int buf_length;
    char aux_msg[FILE_LEN] = {0};
    int i = 0;
    int * snd_id;
    queueADT qres;
    char dir[MAX_DIR_LEN] = {0};
    int cant = 0;
    int id, flag;
    struct msqid_ds mqstat;

    /* Get MQ status info. */
    if (msgctl (mqid, IPC_STAT, &mqstat) == -1)
    {
        fatal(  "ERROR: MQ failed.\n"
                "SOLUTION: Check TCPserver.c.\n");
        exitSplit(splitVal);
    }

    while (doLQ)
    {
        clrtext(name, 100);
        i = 0;
        msg.mtype = 9999;

        flag = 0;
        if ((rtrn = msgrcv(mqid, &msg, FILE_LEN, MAIN_QM_ID, IPC_NOWAIT)) == -1)
        {
            if(errno != ENOMSG)
            {
                printf("msgop: msgrcv failed");
                return (void *)NULL;
            }
            flag = 1;
        }

        if (flag == 0)
        {

            sscanf(msg.mtext, "%d,%s", &com, aux_msg);
            do
            {
                name[i] = aux_msg[i];
                i++;
            }while (aux_msg[i] != ',');

            i++;

            getDirType(&(aux_msg[i]), path, &commtype);

            getDir(dir, path);
            id = userID(name);

            if (com == COM_SND_COMMIT)
            {
                qres = updateIDs(id, dir);
                cant = queueLength(qres);

                sprintf(sbuf.mtext, "%d,%d,%s", SND_FILE, commtype, path);
                buf_length = strlen(sbuf.mtext);

                while (cant--)
                {
                    snd_id = (int *)dequeue ( qres );
                    sbuf.mtype = *snd_id;
                    if (msgsnd(mqid, &sbuf, rtrn, IPC_NOWAIT) < 0)
                    {
                        printf ("%d, %d, %s, %d\n", mqid, (int)sbuf.mtype, sbuf.mtext, buf_length);
                        printf("msgsnd");
                    }

                    free(snd_id);

                }

                freeQueue( qres );
            }
        }
        sleep(SEC_TIMEOUT);
    }
    if (msgctl (mqid, IPC_RMID, &mqstat) == -1)
    {
        fatal(  "ERROR: MQ failed.\n"
                "SOLUTION: Check TCPserver.c.\n");
        exitSplit(splitVal);
    }

    return (void *)NULL;
}

int listenQueueSonTCP(int newsockfd, int type)
{
    struct mymsg msg;
    int com, commtype, rtrn, i;
    char path[FILE_LEN] = {0};

    msg.mtype = type;

    for(i = 0; i < 5; i++)
    {
        if ((rtrn = msgrcv(mqid, &msg, FILE_LEN, type, IPC_NOWAIT)) == -1)
        {
            if(errno != ENOMSG)
            {
                printf("msgop: msgrcv failed\n");
                return -1;
            }

        }
        else
        {
            sscanf(msg.mtext, "%d,%d,%s", &com, &commtype, path);
            printf("msg: %s, id: %d\n", msg.mtext, type);

            if (com == SND_FILE)
            {
                srv_commitTCP(newsockfd, path, commtype);
            }
            return 1;
        }
        usleep(100);
    }

    return 1;
}

int forwardTCP (char * name, char * path, int type)
{
    struct mymsg sbuf;
    int buf_length;

    sprintf(sbuf.mtext, "%d,%s,%s,%d", COM_SND_COMMIT, name, path, type);
    buf_length = strlen(sbuf.mtext);
    sbuf.mtype = MAIN_QM_ID;

    /* Send a message. */
    if (msgsnd(mqid, &sbuf, buf_length, IPC_NOWAIT) < 0)
    {
        printf ("%d, %d, %s, %d\n", mqid, (int)sbuf.mtype, sbuf.mtext, buf_length);
        perror("msgsnd");
        exitSplit(splitVal);
    }

    return 1;
}

void
endCiclesTCP(int signo)
{
    doLC = 0;
    doLQ = 0;

    return;
}

void
closeALLTCP(void)
{
    queueADT q = NULL;
    int *index = NULL;
    int stat;

    printf("\n\nClosing splits.");
    doLC = 0;
    doLQ = 0;

    if (splitVal == 't')
    {
        q = getUsedOnline();
        while((index = dequeue(q)) != NULL)
        {
            pthread_join(splits[*index].thread, NULL);
            printf(".");
            free(index);
        }
        freeQueue(q);
    }
    else
    {
        /*HACK: Mando senial para salir del select*/
        kill(splits[0].cID, SIGUSR1);
        kill(splits[1].cID, SIGUSR1);
        while ((waitpid (-1, &stat, 0)) > 0)
            printf(".");
    }

    close(fdpub);
    printf("\nServer closed\n");
    exitSplit(splitVal);
}

void
sighandLCTCP(int signo)
{
    closeALLTCP();
}
